
# License : GNU GPL 2.0  <http://www.gnu.org/licenses/gpl-2.0.html#SEC3>
# author = Hossam Almeer <hosalmeer@gmail.com>

'''
This class sucks in a file of parameters
'''

import xml.dom.minidom as md
import os
# import pdb

class XMLNode:
    '''
    This class defines an object which represents a node plus it's
    parameters, type, id, parsed from XML.
    The 'parameters' hash is a dict of par_name:par_data pairs.
    '''

    def __init__(self):
        self.id = int()
        self.name = str()
        self.type = str()
        self.data = dict()

    def parameters(self):
        return self.data.keys()
    def values(self):
        return self.data.values()


def bad_xml():
    print "ERROR\n***\nfile is not a valid format\n***"
    return None, None # Returns 2-tuple since parse_par_file returns 2-tuple

def validate_xml(fl,outfile):
    '''
    Checks if xml is valid, pretty prints it to a new file
    '''
    try :
        xm = md.parse(fl)
        pretty = xm.toprettyxml()
        outfile.write(pretty)
    except:
        return bad_xml()

def get_net_name(infile):
    '''
    Gets the networks name from a validated xml file
    '''
    while (1):
        line = infile.readline()
        if ('xml ' not in line) and ( '!' not in line) and ('<' in line):
            if ('<Node>' or '<Link>') in line:
                return bad_xml() # In this case there is no network name
            if 'www' in line:
                line = 
            return line

def get_id(xml_node):
    '''
    Find the id attribute of node/link in XML
    '''
    tmp= xml_node.split('<id>')
    id= tmp[1].split('</id>')
    return int(id[0])

def get_name(xml_node):
    '''
    Find the 'name' attribute of node/link in XML
    '''
    tmp= xml_node.split('<name>')
    name = tmp[1].split('</name>')
    return name[0]

def parse_params(xml):
    '''
    Takes in a chunk of XML that contains parameter and their 
    respective values and insert them into a hash for speedy lookup later.
    Return value is the hash.
    '''

    xml= xml.replace(' ','')
    # Above line should work since there shouldn't be blanks in file
    xml_as_list = xml.split('>')
    xml = list()
    for i in xml_as_list:
        if i:  # Removing empty items
            xml.append(i)
    
    #The stuff in this while loop looks horrible, but it's honestly simple
    # because all it's doing is cutting a string up
    node_hash = dict() # Hash which has all the par_names:par_datas
    counter = 0
    while (counter < len(xml)):
        try:
            node_hash [xml[counter][1:]] =\
                      float(xml[counter+1].split('<')[0])
        except ValueError:    # Hits when float('None') fails
            node_hash [xml[counter][1:]] = None
        counter += 2

    return node_hash


def get_type_and_data(xml_node):
    '''
    Gets the type of a node and all it's parameter values from XML
    '''

    tmp= xml_node.split('<type>')
    tmp = tmp[1].split('</type>')
    type = tmp[0]
    data = tmp[1] # data as raw string
    data = parse_params(data)
    return type,data

 
def parse_par_file(infile,good_xml):
    '''
    Parses an xml file containing node parameters, and outputs a list of
    XMLNode, which derive their attributes entirely from the XML input file
    '''

    validate_xml(infile,good_xml)
     
    good_xml.seek(0,0)
    net_name = get_net_name(good_xml)

    xml = ''
    xml = good_xml.read()
    xml = xml.replace('\n','')
    xml = xml.replace('\t','')

    raw_nodes = xml.split('</Node>')
    if len(raw_nodes) == 1 : #Means that no split on 'Node', implies links
        raw_nodes = xml.split('</Link>')
    print len(raw_nodes)
    if len(raw_nodes) == 1 : #No split on Node or Link implies incompatible file
        return bad_xml()

    raw_nodes = raw_nodes[:-1] # drop last item since it's network name
    x_nodes = list()

    for n in raw_nodes:
        xml_node = XMLNode()
        xml_node.id                    = get_id(n)
        xml_node.name                  = get_name(n)
        xml_node.type, xml_node.data   = get_type_and_data(n)
        x_nodes.append(xml_node)

    infile.close()
    good_xml.close()
    os.remove(good_xml.name) # deletes the pretty printed file, no longer needed

    return net_name, x_nodes


def test():

    fname = 'FFL2dot0.xml'
    # fname = "TRTD.xml"                                                       
    # fname = 'BAD_XML.xml'
    outfile = "outfile.xml"
    outfile = open(outfile,"w+")
    fl = open (fname, 'r')
    parse_par_file(fl,outfile)


if __name__=="__main__":
    test()

